/****************************************************
          File Name:59-4-server.c
          Author: Abby Cin
          Mail: abbytsing@gmail.com
          Created Time: Sun 19 Oct 2014 03:17:12 PM CST
*****************************************************/

#include "59-4.h"
#include "list.h"
#define BACKLOG 10 			/* can NOT handle numerous client */

int main(int argc, char *argv[])
{
	int sfd;
	int ipaddr;
	struct sockaddr_in client;
	struct sockaddr_in addr; /* ip(7) */
	socklen_t len = sizeof(struct sockaddr_in);
	char *client_ip, op, filename[40];
	int act, buf;
	char name[DATA_SIZE];
	int number, slen;
	
    int saved_errno = errno;
    
	client_ip = malloc(DATA_SIZE);
	Node *list;
    
    inet_pton(AF_INET,argv[1],&ipaddr);
	
    bzero(&addr,sizeof(struct sockaddr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(30902);
	addr.sin_addr.s_addr = (ipaddr == 0) ? INADDR_ANY : ipaddr;

	openlog(NULL,LOG_PID|LOG_CONS|LOG_NDELAY|LOG_NOWAIT,LOG_USER);
	sfd = socket(AF_INET,SOCK_DGRAM,0);

	if(bind(sfd,(struct sockaddr *)&addr,len) == -1)
		syslog(LOG_ERR,"bind socket failed");

	if(listen(sfd,BACKLOG) == -1)
		syslog(LOG_ERR,"listen failed");
	bzero(&client,sizeof(struct sockaddr_in));
	for(;;)
	{
		if(recvfrom(sfd,&buf,DATA_SIZE,0,(struct sockaddr *)&client,&len) == -1)
			syslog(LOG_ERR,"recvfrom client failed");
		else
		{
			syslog(LOG_INFO,"%s",inet_ntop(AF_INET,&client.sin_addr,client_ip,DATA_SIZE));
			syslog(LOG_INFO,"%d",buf);
		}
		
		if(buf == 1)
		{
			memset(filename,0,40);
			recvfrom(sfd,filename,40,0,(SA *)&client,&len);
			slen=strlen(filename);
			filename[slen-1]='\0'; /* remove last '\n' */
            list=lopen(filename);
            sendto(sfd,&errno,sizeof(errno),0,(SA *)&client,len);
			if(list == (Node *)-1)
            {
               // if(errno == EBADF)
                 //   remove(filename);
                errno = saved_errno;
                continue;
            }
		}
		else if(buf == 2)
		{
			/* 'size' arg in memset and recvfrom is SOOO IMPORTANT */
			memset(filename,0,40);
			recvfrom(sfd,filename,40,0,(SA *)&client,&len);
			slen=strlen(filename);
			filename[slen-1]='\0'; /* remove last '\n' */
			recvfrom(sfd,&buf,sizeof(buf),0,(SA *)&client,&len);
			if((list=lcreate(buf,sfd)) == (Node *)-1)
			{
				perror("lcreat");
				exit(1);
			}
		}
		else
			continue;

		for(;;)
		{
			recvfrom(sfd,&op,sizeof(op),0,(SA *)&client,&len);
            if(op == 'q')
            {
				save(list,filename);
                destroy(list);
                break; /* for another client */
            }
			switch(op) 		/* transform buf to 'int' */
			{
				case 'h':
					show(list,sfd,(SA *)&client);
					break;
				case 'o':
					/* get number */
					recvfrom(sfd,&act,DATA_SIZE,0,(SA *)&addr,&len);
					number = act;
					/*get name */
					recvfrom(sfd,name,DATA_SIZE,0,(SA *)&addr,&len);
					modify(list,number,name);
					memset(name,0,sizeof(name));
					break;
				case 'd': 				/* ldelete */
					recvfrom(sfd,&act,DATA_SIZE,0,(SA *)&addr,&len);
					number = act;
					ldelete(&list,number);
					break;
				case 'n':
					recvfrom(sfd,&act,DATA_SIZE,0,(SA *)&addr,&len);
					number = act;
					recvfrom(sfd,name,DATA_SIZE,0,(SA *)&addr,&len);
					insert(&list,number,name);
					memset(name,0,sizeof(name));
					break;
				case 'f':
					recvfrom(sfd,&act,DATA_SIZE,0,(SA *)&addr,&len);
					number = act;
					lfind(list,number);
					break;
				case 's':
					save(list,filename);
					break;
				default:
					break;
			}
		}
	}
}
